package rcp.iphex2.ui.heatmapexplorer;

import java.awt.Color;
import java.util.ArrayList;

import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.part.ViewPart;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.annotations.XYBoxAnnotation;
import org.jfree.chart.annotations.XYLineAnnotation;
import org.jfree.chart.annotations.XYTextAnnotation;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYBlockRenderer;
import org.jfree.data.xy.DefaultXYZDataset;
import org.jfree.ui.TextAnchor;

import rcp.iphex2.model.AreaAnnotation;
import rcp.iphex2.model.DEFINITIONS;
import rcp.iphex2.model.HeatmapData;
import rcp.iphex2.model.Peak;
import rcp.iphex2.model.Peaklist;
import rcp.iphex2.model.Project;
import rcp.iphex2.model.ProjectEntry;


public class HeatmapExplorerView extends ViewPart implements ISelectionListener {
	private JFreeChart chart;
	private ISelection previousSelection;
	private boolean addAnnotation = false;
	private ChartPanel cp;
	private AddAnnotationListener addAnnotationListener;
	private Project project;
	private ProjectEntry projectEntry;
	
	public HeatmapExplorerView() {
		// TODO Auto-generated constructor stub
	}

	private void initChart(Composite parent) {
		NumberAxis RTaxis = new NumberAxis("RT");
		NumberAxis K0axis = new NumberAxis("1/k0");
		K0axis.setAutoTickUnitSelection(true);

		XYPlot heatmapPlot = new XYPlot(null, K0axis, RTaxis, null);
		chart = new JFreeChart(heatmapPlot);

		cp = ChartTools.addChartToCompoiste(chart, parent);

		HeatmapMouseListener heatmapMouseListener = new HeatmapMouseListener(cp);
		cp.addMouseMotionListener(heatmapMouseListener);
		cp.addMouseListener(heatmapMouseListener);

		addAnnotationListener = new AddAnnotationListener(this,cp);
		
		// does not work on imported swing components atm
		cp.addMouseWheelListener(heatmapMouseListener);

	}
	
	
	
	public void updateAnnotations(){
		chart.getXYPlot().clearAnnotations();
		Peaklist peaklist = projectEntry.getPeaklist();
		if (peaklist != null) showPeaklist(peaklist);
		showAreaAnnotations(project.getAreaAnnotations());
	}
	
	private void showProjectEntry(ProjectEntry projectEntry){
		this.projectEntry = projectEntry;
		this.project = projectEntry.getRootProject();
		chart.getXYPlot().clearAnnotations();
		String measurementFilename = projectEntry.getMeasurement().getPath();
		showHeatmap(measurementFilename);
		
		Peaklist peaklist = projectEntry.getPeaklist();
		if (peaklist != null) showPeaklist(peaklist);
		showAreaAnnotations(project.getAreaAnnotations());
	}

	private void showHeatmap(String filename) {
		HeatmapData heatmapData = new HeatmapData(filename);
		DefaultXYZDataset imsdds = new DefaultXYZDataset();

		imsdds.addSeries(heatmapData.getFilename(), heatmapData.getJfcmap());
		chart.getXYPlot().setDataset(imsdds);

		double avarageK0Distance = heatmapData.getScaleK0()[heatmapData
				.getScaleK0().length - 1]
				/ heatmapData.getScaleK0().length;
		double avarageTimeDistance = heatmapData.getScaleRT()[heatmapData
				.getScaleRT().length - 1] / (heatmapData.getScaleRT().length);
		XYBlockRenderer xybr = ChartTools.createHeatmapRenderer(40,
				avarageK0Distance, avarageTimeDistance);

		chart.getXYPlot().setRenderer(xybr);
		heatmapData.saveToCache();
	}

	public void showPeaklist(Peaklist peaklist) {
		for (Peak p : peaklist.getPeaks()) {
			XYLineAnnotation xyRtLine = new XYLineAnnotation(p.dt - p.dtSize
					/ 2, p.rt, p.dt + p.dtSize / 2, p.rt);
			XYLineAnnotation xyDtLine = new XYLineAnnotation(p.dt, p.rt
					- p.rtSize / 2, p.dt, p.rt + p.rtSize / 2);
			chart.getXYPlot().addAnnotation(xyDtLine);
			chart.getXYPlot().addAnnotation(xyRtLine);
		}

	}
	
	private void showAreaAnnotations(ArrayList<AreaAnnotation> areaAnnotations){
		for (AreaAnnotation aa : areaAnnotations) {
            double alignedRT = aa.getRt();
            XYBoxAnnotation xyb = new XYBoxAnnotation(aa.getDt() - aa.getDtTolerance(), alignedRT - aa.getRtTolerance(), aa.getDt() + aa.getDtTolerance(), alignedRT + aa.getRtTolerance());
            chart.getXYPlot().addAnnotation(xyb);
            
//            XYLineAnnotation top = new XYLineAnnotation(aa.getDt() - aa.getDtTolerance(), alignedRT + aa.getRtTolerance(), aa.getDt() + aa.getDtTolerance(), alignedRT + aa.getRtTolerance());
//            XYLineAnnotation bot = new XYLineAnnotation(aa.getDt() - aa.getDtTolerance(), alignedRT - aa.getRtTolerance(), aa.getDt() + aa.getDtTolerance(), alignedRT - aa.getRtTolerance());
//            XYLineAnnotation rig = new XYLineAnnotation(aa.getDt() + aa.getDtTolerance(), alignedRT + aa.getRtTolerance(), aa.getDt() + aa.getDtTolerance(), alignedRT - aa.getRtTolerance());
//            XYLineAnnotation lef = new XYLineAnnotation(aa.getDt() - aa.getDtTolerance(), alignedRT + aa.getRtTolerance(), aa.getDt() - aa.getDtTolerance(), alignedRT - aa.getRtTolerance());
//            chart.getXYPlot().addAnnotation(top);
//            chart.getXYPlot().addAnnotation(bot);
//            chart.getXYPlot().addAnnotation(lef);
//            chart.getXYPlot().addAnnotation(rig);

            
            
            XYTextAnnotation xyt = new XYTextAnnotation(aa.getName(), aa.getDt(), alignedRT + aa.getRtTolerance());
            xyt.setFont(DEFINITIONS.ANNOTATION_FONT);
            xyt.setTextAnchor(TextAnchor.BOTTOM_CENTER);
            Color transparentWhite = new Color(255, 255, 255, 100);
            xyt.setBackgroundPaint(transparentWhite);
            chart.getXYPlot().addAnnotation(xyt);
        }
	}
	

	@Override
	public void createPartControl(Composite parent) {
		initChart(parent);
		getSite().getPage().addSelectionListener(this);
	}

	@Override
	public void setFocus() {
	}

	@Override
	public void selectionChanged(IWorkbenchPart part, ISelection selection) {
		if (!selection.isEmpty()) {
		//TODO: analyse and find method without projectexplorer view reference 
			//	if (part.getClass() == ProjectExplorerView.class) {
				IStructuredSelection iss = (IStructuredSelection) selection;
				Object object = iss.getFirstElement();
				if (object instanceof ProjectEntry
						&& this.getSite().getPage().isPartVisible(this)
						&& !selection.equals(previousSelection)) {
					ProjectEntry projectEntry = (ProjectEntry) object;
					showProjectEntry(projectEntry);
					System.out.println("pong");
				}
				previousSelection = selection;
		//	}
		}
	}

	public void toggleAddAnnotation(){
		if (addAnnotation == false){
			addAnnotation = true;
			addAnnotationListener.setProject(project);
			cp.addChartMouseListener(addAnnotationListener);
		}
		else{
			addAnnotation = false;
			cp.removeChartMouseListener(addAnnotationListener);
		}
	}

}
